﻿/*----------------------------------------------------------------
//  <copyright file="MicroCloudJwtBearerEvents.cs" company="MicroCloud@151504200868">
//      Copyright © 2020-2024 MicroCloud Corporation, All rights reserved.
//  </copyright>
//  <site>https://gitee.com/chenmm123/microclouds</site>
//  <last-editor>cmm</last-editor>
//  <last-date>2023-02-20 18:00</last-date>
//----------------------------------------------------------------*/

namespace MicroCloud.Authentication.JwtBearer
{
    #region "自定义JwtBearerEvents"
    /// <summary>
    /// 自定义JwtBearerEvents
    /// </summary>
    public class MicroCloudJwtBearerEvents : JwtBearerEvents
    {
        //字段
        private readonly IServiceCollection _services;
        private readonly MicroCloudOptions _options;

        #region "构造函数"
        #region "初始化一个<see cref="MicroCloudJwtBearerEvents"/>类型的新实例"
        /// <summary>
        /// 初始化一个<see cref="MicroCloudJwtBearerEvents"/>类型的新实例
        /// </summary>
        /// <param name="services">依赖注入服务容器</param>
        public MicroCloudJwtBearerEvents(IServiceCollection services)
        {
            _services = services;
            _options = _services.GetMicroCloudOptions();
        }
        #endregion

        #endregion

        #region "方法"
        #region "Token验证通过时，从OnlineUser缓存或数据库查找用户的最新信息附加到有效的 ClaimPrincipal 上"
        /// <summary>
        /// Token验证通过时，从OnlineUser缓存或数据库查找用户的最新信息附加到有效的 ClaimPrincipal 上
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task TokenValidated(TokenValidatedContext context)
        {
            ClaimsPrincipal user = context.Principal;
            ClaimsIdentity identity = user.Identity as ClaimsIdentity;

            IUserClaimsProvider accessClaimsProvider = context.HttpContext.RequestServices.GetService<IUserClaimsProvider>();
            OperationResult<ClaimsIdentity> result = await accessClaimsProvider.RefreshIdentity(identity);
            if (!result.Succeeded)
            {
                context.Fail(result.Message);
            }
        }
        #endregion
        #region "在接收消息时触发，这里定义接收SignalR的token的逻辑"
        /// <summary>
        /// 在接收消息时触发，这里定义接收SignalR的token的逻辑
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task MessageReceived(MessageReceivedContext context)
        {
            //string token = context.Request.Query["access_token"];
            //string path = context.HttpContext.Request.Path;
            //if (!string.IsNullOrEmpty(token) && path.Contains("hub"))
            //{
            //    context.Token = token;
            //}
            //return Task.CompletedTask;

            if (_options?.SignalR?.Enabled != true)
            {
                return Task.CompletedTask;
            }
            string signalrPattern = _options?.SignalR?.RoutePattern;
            if (signalrPattern.IsMissing())
            {
                return Task.CompletedTask;
            }

            if (!context.HttpContext.Request.Path.HasValue)
            {
                return Task.CompletedTask;
            }
            //重点在于这里；判断Signalr的路径
            var token = "";
            var headAuthorization = context.HttpContext.Request.Headers["Authorization"];
            if (headAuthorization.Count > 0)
            {
                token = headAuthorization.ToString().Replace($"{JwtBearerDefaults.AuthenticationScheme} ", "").Trim();
            }
            var accessToken = context.HttpContext.Request.Query["access_token"];
            if (!string.IsNullOrWhiteSpace(accessToken))
            {
                token = accessToken.ToString();
            }
            if (!string.IsNullOrWhiteSpace(token))
            {
                var path = context.HttpContext.Request.Path;
                if (!string.IsNullOrWhiteSpace(token) && path.StartsWithSegments(signalrPattern))
                {
                    context.Token = token;
                    return Task.CompletedTask;
                }
            }

            return Task.CompletedTask;
        }
        #endregion
        #region "身份验证失败"
        /// <summary>
        /// 身份验证失败
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override Task AuthenticationFailed(AuthenticationFailedContext context)
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Append("Token-Expired", "true");
            }

            return Task.CompletedTask;
        }
        #endregion

        #endregion

    }
    #endregion

}
